<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <style type="text/css">
        input[type="text"] {width: 300px;}
        .muted {color: #CCCCCC;font-size: 10px;}
    </style>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/centrifugal/centrifuge-js@master/dist/centrifuge.min.js"></script>
    <script type="text/javascript">
        // helper functions to work with escaping html.
        const tagsToReplace = {'&': '&amp;', '<': '&lt;', '>': '&gt;'};

        function replaceTag(tag) {
            return tagsToReplace[tag] || tag;
        }

        function safeTagsReplace(str) {
            return str.replace(/[&<>]/g, replaceTag);
        }

        const channel = "chat:index";

        window.addEventListener('load', function() {
            const input = document.getElementById("input");
            const container = document.getElementById('messages');

            const centrifuge = new Centrifuge('ws://localhost:8080/connection/websocket');

            centrifuge.setConnectData({"user-agent": navigator.userAgent});

            // bind listeners on centrifuge object instance events.
            centrifuge.on('connect', function (ctx) {
                drawText('Connected with client ID ' + ctx.client + ' over ' + ctx.transport + ' as user: ' + ctx.data.email);
                input.removeAttribute('disabled');
            });

            centrifuge.on('message', function (data) {
                drawText(JSON.stringify(data));
                // echo data back to server.
                centrifuge.send(data);
            });

            centrifuge.on('disconnect', function (ctx) {
                drawText('Disconnected: ' + ctx.reason + (ctx.reconnect ? ", will try to reconnect" : ", won't try to reconnect"));
                input.setAttribute('disabled', 'true');
            });

            // subscribe on channel and bind various event listeners. Actual
            // subscription request will be sent after client connects to
            // a server.
            const sub = centrifuge.subscribe(channel, handleMessage)
                .on("join", handleJoin)
                .on("leave", handleLeave)
                .on("unsubscribe", handleUnsubscribe)
                .on("subscribe", handleSubscribe)
                .on("error", handleSubscribeError);

            // Trigger actual connection establishing with a server.
            // At this moment actual client work starts - i.e. subscriptions
            // defined start subscribing etc.
            centrifuge.connect();

            function handleSubscribe(ctx) {
                drawText('Subscribed on channel ' + ctx.channel + ' (resubscribed: ' + ctx.isResubscribe + ', recovered: ' + ctx.recovered + ')');
                // This can be whatever JSON you want.
                const rpcRequest = {"method": "getCurrentYear"};
                centrifuge.rpc(rpcRequest).then(function (data) {
                    drawText(JSON.stringify(data));
                }, function (err) {
                    drawText("RPC error: " + JSON.stringify(err));
                });
            }

            function handleSubscribeError(err) {
                drawText('Error subscribing on channel ' + err.channel + ': ' + err.message);
            }

            function handleMessage(message) {
                let clientID;
                if (message.info) {
                    clientID = message.info.client;
                } else {
                    clientID = null;
                }
                const inputText = message.data["input"].toString();
                const text = safeTagsReplace(inputText) + ' <span class="muted">from ' + clientID + '</span>';
                drawText(text);
            }

            function handleJoin(message) {
                drawText('Client joined channel ' + this.channel + ' (uid ' + message.info["client"] + ', user ' + message.info["user"] + ')');
            }

            function handleLeave(message) {
                drawText('Client left channel ' + this.channel + ' (uid ' + message.info["client"] + ', user ' + message.info["user"] + ')');
            }

            function handleUnsubscribe(sub) {
                drawText('Unsubscribed from channel ' + sub.channel);
            }

            function drawText(text) {
                let e = document.createElement('li');
                e.innerHTML = [(new Date()).toString(), ' ' + text].join(':');
                container.insertBefore(e, container.firstChild);
            }

            document.getElementById('form').addEventListener('submit', function(event) {
                event.preventDefault();
                sub.publish({"input": input.value}).then(function () {
                    // console.log('message accepted by server');
                }, function (err) {
                    // console.log('error publishing message', err);
                });
                input.value = '';
            });
        });
    </script>
</head>
<body>
<form id="form">
    <input type="text" id="input" autocomplete="off"/>
    <input type="submit" id="submit" value="»">
</form>
<ul id="messages"></ul>
</body>
</html>
